/*
 * Copyright (c) 2008 CO-CONV, Corp. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#ifndef _SYS_SYSCALL_H_
#define _SYS_SYSCALL_H_

#ifndef CTL_CODE
#include <devioctl.h>
#endif

#define DD_SCTP_ONE_TO_ONE_DEVICE_NAME L"\\Device\\SctpTcp"
#define DD_SCTP_ONE_TO_MANY_DEVICE_NAME L"\\Device\\SctpUdp"
#define DD_SCTP_DEVICE_NAME L"\\Device\\Sctp"
#define DD_SCTP_SOCKET_DEVICE_NAME L"\\Device\\SctpSocket"
#define WIN_SCTP_BASE_DEVICE_NAME L"Sctp"
#define WIN_SCTP_DEVICE_NAME L"\\\\.\\" WIN_SCTP_BASE_DEVICE_NAME

#define FSCTL_TCP_BASE	FILE_DEVICE_NETWORK

#define _TCP_CTL_CODE(function, method, access) \
	CTL_CODE(FSCTL_TCP_BASE, function, method, access)

#define IOCTL_TCP_QUERY_INFORMATION_EX  \
	_TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_TCP_SET_INFORMATION_EX  \
	_TCP_CTL_CODE(1, METHOD_BUFFERED, FILE_WRITE_DATA)	

#define FSCTL_SCTP_BASE	FILE_DEVICE_NETWORK

#define _SCTP_CTL_CODE(function, method, access) \
	CTL_CODE(FSCTL_SCTP_BASE, function, method, access)

#define IOCTL_SCTP_SYSCTL \
	_SCTP_CTL_CODE(0, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)

typedef struct _SOCKET_WSABUF {
	UINT	len;
	PCHAR	buf;
} SOCKET_WSABUF, *PSOCKET_WSABUF;

typedef struct _SOCKET_WSAMSG {
	LPSOCKADDR name;
	INT	namelen;
	PSOCKET_WSABUF lpBuffers;
	DWORD	dwBufferCount;
	SOCKET_WSABUF	Control;
	DWORD	dwFlags;
} SOCKET_WSAMSG, *PSOCKET_WSAMSG;

typedef struct _SOCKET_FD_SET {
	UINT	fd_count;
	HANDLE	fd_array[0];
} SOCKET_FD_SET, *PSOCKET_FD_SET;

typedef struct _SOCKET_TIMEVAL {
	long	tv_sec;
	long	tv_usec;
} SOCKET_TIMEVAL, *PSOCKET_TIMEVAL;

typedef struct _SOCKET_OVERLAPPED {
	ULONG_PTR	Internal;
	ULONG_PTR	InternalHigh;
	union {
		struct {
			DWORD Offset;
			DWORD OffsetHigh;
		};
		PVOID Pointer;
	};
	HANDLE hEvent;
} SOCKET_OVERLAPPED, *PSOCKET_OVERLAPPED;

#define SOCKET_FD_READ_BIT	0
#define SOCKET_FD_READ		(1 << FD_READ_BIT)
#define SOCKET_FD_WRITE_BIT	1
#define SOCKET_FD_WRITE         (1 << FD_WRITE_BIT)
#define SOCKET_FD_OOB_BIT	2
#define SOCKET_FD_OOB		(1 << FD_OOB_BIT)
#define SOCKET_FD_ACCEPT_BIT	3
#define SOCKET_FD_ACCEPT	(1 << FD_ACCEPT_BIT)
#define SOCKET_FD_CONNECT_BIT	4
#define SOCKET_FD_CONNECT	(1 << FD_CONNECT_BIT)
#define SOCKET_FD_CLOSE_BIT	5
#define SOCKET_FD_CLOSE		(1 << FD_CLOSE_BIT)
#define SOCKET_FD_QOS_BIT       6
#define SOCKET_FD_QOS		(1 << FD_QOS_BIT)
#define SOCKET_FD_GROUP_QOS_BIT	7
#define SOCKET_FD_GROUP_QOS	(1 << FD_GROUP_QOS_BIT)
#define SOCKET_FD_ROUTING_INTERFACE_CHANGE_BIT 8
#define SOCKET_FD_ROUTING_INTERFACE_CHANGE (1 << FD_ROUTING_INTERFACE_CHANGE_BIT)
#define SOCKET_FD_ADDRESS_LIST_CHANGE_BIT 9
#define SOCKET_FD_ADDRESS_LIST_CHANGE (1 << FD_ADDRESS_LIST_CHANGE_BIT)
#define SOCKET_FD_MAX_EVENTS    10
#define SOCKET_FD_ALL_EVENTS	((1 << FD_MAX_EVENTS) - 1)

#define SOCKET_IOCPARM_MASK	0x7f
#define SOCKET_IOC_VOID		0x20000000
#define SOCKET_IOC_OUT		0x40000000
#define SOCKET_IOC_IN		0x80000000
#define SOCKET_IOC_INOUT	(SOCKET_IOC_IN | SOCKET_IOC_OUT)
#define SOCKET_IO(x, y)		(SOCKET_IOC_VOID | ((x) << 8) | (y))
#define SOCKET_IOR(x, y, t)	(SOCKET_IOC_OUT | (((long)sizeof(t) & SOCKET_IOCPARM_MASK) << 16) | ((x) << 8) | (y))
#define SOCKET_IOW(x, y, t)	(SOCKET_IOC_IN | (((long)sizeof(t) & SOCKET_IOCPARM_MASK) << 16)| ((x) << 8) | (y))

#define SOCKET_FIONBIO		SOCKET_IOW('f', 126, u_long)

typedef struct _SOCKET_WSANETWORKEVENTS {
	long lNetworkEvents;
	int iErrorCode[SOCKET_FD_MAX_EVENTS];
} SOCKET_WSANETWORKEVENTS,  *LPSOCKET_WSANETWORKEVENTS;


typedef struct _SOCKET_OPEN_REQUEST {
	int	af;
	int	type;
	int	protocol;
} SOCKET_OPEN_REQUEST , *PSOCKET_OPEN_REQUEST;

typedef struct _SOCKET_ACCEPT_REQUEST {
	struct sockaddr	*addr;
	int		addrlen;
	HANDLE		socket;
} SOCKET_ACCEPT_REQUEST, *PSOCKET_ACCEPT_REQUEST;

typedef struct _SOCKET_SEND_REQUEST {
	PSOCKET_WSABUF	lpBuffers;
	DWORD		dwBufferCount;
	struct sockaddr	*lpTo;
	int		iTolen;
	DWORD		dwFlags;
	PSOCKET_OVERLAPPED lpOverlapped;
} SOCKET_SEND_REQUEST, *PSOCKET_SEND_REQUEST;

typedef struct _SOCKET_SENDMSG_REQUEST {
	PSOCKET_WSAMSG	lpMsg;
	DWORD		dwFlags;
	PSOCKET_OVERLAPPED lpOverlapped;
} SOCKET_SENDMSG_REQUEST, *PSOCKET_SENDMSG_REQUEST;

typedef struct _SOCKET_RECV_REQUEST {
	PSOCKET_WSABUF	lpBuffers;
	DWORD		dwBufferCount;
	struct sockaddr	*lpFrom;
	int		*lpFromlen;
	DWORD		*lpFlags;
	PSOCKET_OVERLAPPED lpOverlapped;
} SOCKET_RECV_REQUEST, *PSOCKET_RECV_REQUEST;

typedef struct _SOCKET_RECVMSG_REQUEST {
	PSOCKET_WSAMSG	lpMsg;
	PSOCKET_OVERLAPPED lpOverlapped;
} SOCKET_RECVMSG_REQUEST, *PSOCKET_RECVMSG_REQUEST;

typedef struct _SOCKET_SELECT_REQUEST {
	int		fd_setsize;
	int		nfds;
	PSOCKET_FD_SET	readfds;
	PSOCKET_FD_SET	writefds;
	PSOCKET_FD_SET	exceptfds;
	SOCKET_TIMEVAL	timeout;
	BOOLEAN		infinite;
} SOCKET_SELECT_REQUEST, *PSOCKET_SELECT_REQUEST;

typedef struct _SOCKET_EVENTSELECT_REQUEST {
	HANDLE		hEventObject;
	LONG		lNetworkEvents;
} SOCKET_EVENTSELECT_REQUEST, *PSOCKET_EVENTSELECT_REQUEST;

typedef struct _SOCKET_ENUMNETWORKEVENTS_REQUEST {
	HANDLE		hEventObject;
	SOCKET_WSANETWORKEVENTS networkEvents;
} SOCKET_ENUMNETWORKEVENTS_REQUEST, *PSOCKET_ENUMNETWORKEVENTS_REQUEST;

typedef struct _SOCKET_SOCKOPT_REQUEST {
	int		level;
	int		optname;
	char		*optval;
	int		optlen;
} SOCKET_SOCKOPT_REQUEST, *PSOCKET_SOCKOPT_REQUEST;

typedef struct _SOCKET_SCTPSEND_REQUEST {
	void		*data;
	size_t		len;
	struct sockaddr *to;
	int		tolen;
	struct sctp_sndrcvinfo *sinfo;
	int		flags;
} SOCKET_SCTPSEND_REQUEST, *PSOCKET_SCTPSEND_REQUEST;

typedef struct _SOCKET_SCTPRECV_REQUEST {
	void		*data;
	size_t		len;
	struct sockaddr *from;
	int		*fromlen;
	struct sctp_sndrcvinfo *sinfo;
	int		*msg_flags;
} SOCKET_SCTPRECV_REQUEST, *PSOCKET_SCTPRECV_REQUEST;

typedef struct _SOCKET_PEELOFF_REQUEST {
	HANDLE		socket;
	ULONG		assoc_id;
} SOCKET_PEELOFF_REQUEST, *PSOCKET_PEELOFF_REQUEST ;

typedef struct _SOCKET_IOCTL_REQUEST {
	HANDLE		socket;
	DWORD		dwIoControlCode;
	PVOID		lpvInBuffer;
	DWORD		cbInBuffer;
	PVOID		lpvOutBuffer;
	DWORD		cbOutBuffer;
} SOCKET_IOCTL_REQUEST, *PSOCKET_IOCTL_REQUEST;

#define ProtocolInfo		"ProtocolInfo"

#define FSCTL_SOCKET_BASE	FILE_DEVICE_NETWORK

#define _SOCKET_CTL_CODE(function, method, access) \
	CTL_CODE(FSCTL_SOCKET_BASE, function, method, access)

#define IOCTL_SOCKET_OPEN \
	_SOCKET_CTL_CODE(0, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_GET_PROTOINFO \
	_SOCKET_CTL_CODE(1, METHOD_OUT_DIRECT, FILE_WRITE_DATA)

#define IOCTL_SOCKET_BIND \
	_SOCKET_CTL_CODE(2, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_CONNECT \
	_SOCKET_CTL_CODE(3, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_LISTEN \
	_SOCKET_CTL_CODE(4, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_ACCEPT \
	_SOCKET_CTL_CODE(5, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)

#define IOCTL_SOCKET_SEND \
	_SOCKET_CTL_CODE(6, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_SENDDISCONNECT \
	_SOCKET_CTL_CODE(7, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_SENDTO \
	_SOCKET_CTL_CODE(8, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_SENDMSG \
	_SOCKET_CTL_CODE(9, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_RECV \
	_SOCKET_CTL_CODE(10, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_RECVDISCONNECT \
	_SOCKET_CTL_CODE(11, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_RECVFROM \
	_SOCKET_CTL_CODE(12, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_RECVMSG \
	_SOCKET_CTL_CODE(13, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_SELECT \
	_SOCKET_CTL_CODE(14, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)

#define IOCTL_SOCKET_EVENTSELECT \
	_SOCKET_CTL_CODE(15, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)

#define IOCTL_SOCKET_ENUMNETWORKEVENTS \
	_SOCKET_CTL_CODE(16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)

#define IOCTL_SOCKET_SETSOCKOPT \
	_SOCKET_CTL_CODE(17, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_GETSOCKOPT \
	_SOCKET_CTL_CODE(18, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_GETSOCKNAME \
	_SOCKET_CTL_CODE(19, METHOD_OUT_DIRECT, FILE_WRITE_DATA)

#define IOCTL_SOCKET_GETPEERNAME \
	_SOCKET_CTL_CODE(20, METHOD_OUT_DIRECT, FILE_WRITE_DATA)

#define IOCTL_SOCKET_SHUTDOWN \
	_SOCKET_CTL_CODE(21, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_SCTPSEND \
	_SOCKET_CTL_CODE(22, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_SCTPRECV \
	_SOCKET_CTL_CODE(23, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_SOCKET_PEELOFF \
	_SOCKET_CTL_CODE(24, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)

#define IOCTL_SOCKET_IOCTL \
	_SOCKET_CTL_CODE(25, METHOD_BUFFERED, FILE_READ_DATA)

#endif /* _SYS_SYSCALL_H_ */
